package org.i1510.base.load;

import java.io.File;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.sigar.NetInterfaceConfig;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.Sigar;

/**
 * @author rambo application 注解
 * @ServletComponentScan(value="org.i1510.base.load")
 * win系统需要在环境变量path中增加目录
 * 在win dos输入 chcp 65001 字体设置为 Lucida Console 
 */
@WebListener
public final class PluginContextLoaderListener implements
		ServletContextListener {
	private Log logger = LogFactory.getLog(PluginContextLoaderListener.class);

	public static void main(String[] args) {
		File file = new File(".");
		System.out.println(System.getProperty("user.dir"));
	}

	public boolean isOSWin() {// OS 版本判断
		String OS = System.getProperty("os.name").toLowerCase();
		if (OS.indexOf("win") >= 0) {
			return true;
		} else
			return false;
	}

	private void check() {
		try {

			String sigarLibPath = System.getProperty("user.dir")
					+ "/src/main/webapp/lib/sigar";

			String path = System.getProperty("java.library.path");
			if (!path.contains(sigarLibPath)) {
				if (isOSWin()) {
					path += ";" + sigarLibPath;
				} else {
					path += ":" + sigarLibPath;
				}
				System.setProperty("java.library.path", path);
			}

			Sigar sigar = new Sigar();
			try {
				printHwadd(sigar);
				try {
					checkJVM();
					checkOS(sigar);
					checkCpu(sigar);
					checkMem(sigar);
				} catch (Throwable e) {
					this.logger.warn("检查本地信息发生错误", e);
				}
			} finally {
				sigar.close();
			}
		} catch (UnsatisfiedLinkError e) {
			this.logger.error("无法获取本地信息");
		} catch (Throwable e) {
			this.logger.error("无法获取本地信息", e);
		}
	}

	private void printHwadd(Sigar sigar) {
		try {
			String jip = System.getProperty("jgroups.bind_addr");
			if (jip != null) {
				jip = jip.trim();
				if (jip.length() == 0) {
					jip = null;
				}
			}
			List ipList = new ArrayList();
			List hwaddrList = new ArrayList();

			Enumeration nets = NetworkInterface.getNetworkInterfaces();
			String ipAddr;
			byte[] mac;
			StringBuffer sb;
			while (nets.hasMoreElements()) {
				NetworkInterface net = (NetworkInterface) nets.nextElement();
				if ((!net.isLoopback()) && (net.isUp())) {
					Enumeration addrs = net.getInetAddresses();
					ipAddr = null;
					while (addrs.hasMoreElements()) {
						InetAddress addr = (InetAddress) addrs.nextElement();
						if ((addr instanceof Inet4Address)) {
							ipAddr = addr.getHostAddress();
							break;
						}
					}

					mac = net.getHardwareAddress();
					if ((mac != null) && (mac.length != 0)) {
						sb = new StringBuffer();
						for (int i = 0; i < mac.length; i++) {
							if (i != 0) {
								sb.append(":");
							}
							int temp = mac[i] & 0xFF;
							String str = Integer.toHexString(temp);
							if (str.length() == 1)
								sb.append("0" + str);
							else {
								sb.append(str);
							}
						}
						if (ipAddr != null) {
							hwaddrList.add(sb.toString().toLowerCase());
							ipList.add(ipAddr);
						}
					}
				}
			}
			if (hwaddrList.isEmpty()) {
				String[] ifaces = sigar.getNetInterfaceList();
				// mac = (sb = ifaces).length;

				for (int i = 0; i < ifaces.length; i++) {
					String iface = ifaces[i];
					NetInterfaceConfig cfg = sigar.getNetInterfaceConfig(iface);
					String ip = cfg.getAddress();
					String hwaddr = cfg.getHwaddr();
					if ((hwaddr != null) && (ip != null)) {
						if ((jip == null) || (jip.equals(ip))) {
							if ((!"127.0.0.1".equals(ip))
									&& (!"0.0.0.0".equals(ip))
									&& (!"::".equals(ip))
									&& (!"00:00:00:00:00:00".equals(hwaddr))) {
								hwaddr = hwaddr.replace('-', ':').toLowerCase();
								if (!hwaddrList.contains(hwaddr)) {
									ipList.add(ip);
									hwaddrList.add(hwaddr);
								}
							}
						}
					}
				}
			}
			if (hwaddrList.isEmpty()) {
				if (jip == null)
					this.logger.warn("无法获取的网卡地址，可能会导致正式版的license失效");
				else
					this.logger.warn("无法获取IP（" + jip
							+ "）对应的网卡，可能会导致正式版的license失效，"
							+ "请检查jgroups.bind_addr参数的设定是否正确");
			} else {
				System.out.println("本地网络IP：" + (String) ipList.get(0)
						+ "，网卡物理地址：" + (String) hwaddrList.get(0));
				if (hwaddrList.size() > 1)
					this.logger
							.warn("获取本地网卡地址时，出现多个网卡，可能会导致正式版的license失效，建议通过JVM参数“-Djgroups.bind_addr=ip地址”，绑定本机地址");
			}
		} catch (Throwable e) {
			this.logger.error("获取网卡物理地址失败，可能会导致正式版的license失效", e);
		}
	}

	private void checkJVM() {
		String version = System.getProperty("java.specification.version");
		if ((version != null) && (version.compareTo("1.6") < 0))
			this.logger.warn("当前的JVM版本号为：" + version + "，请使用1.6或以上的版本");
	}

	private void checkOS(Sigar sigar) throws Exception {
		OperatingSystem OS = OperatingSystem.getInstance();
		if ("32".equals(OS.getDataModel()))
			this.logger.warn("当前操作系统或JVM的位数为：32-Bit，建议使用64-Bit");
	}

	private void checkCpu(Sigar sigar) throws Exception {
		int mcpu = sigar.getCpuInfoList().length;
		int jcpu = Runtime.getRuntime().availableProcessors();
		if ((mcpu < 4) || (jcpu < 4))
			this.logger.warn("当前机器CPU个数为：" + mcpu + "，JVM可用CPU个数为：" + jcpu
					+ "，建议不少于4");
	}

	private void checkMem(Sigar sigar) throws Exception {
		long mMem = sigar.getMem().getTotal() / 1024L / 1024L;
		if (mMem < 4000L) {
			this.logger.warn("当前机器总内存：" + mMem + "M，建议不小于4,096M");
		}

		long jMem = Runtime.getRuntime().maxMemory() / 1024L / 1024L;
		if (jMem < 2000L)
			this.logger.warn("当前JVM可使用最大内存：" + jMem + "M，建议不小于2,048M");
	}

	public void contextInitialized(ServletContextEvent event) {
		check();
		System.out.println("[i1510]->contextInitialized");
	}

	public void contextDestroyed(ServletContextEvent event) {
		System.out.println("[i1510]->contextDestroyed");
	}

}